package com.wx.service.impl;

import com.wx.constants.RedisKeyPrefix;
import com.wx.exception.BusinessException;
import com.wx.service.RedisService;
import com.wx.service.SysGeneratorCodeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 * <p>Title:      SysGeneratorCodeServiceImpl. </p>
 * <p>Description 自动生成Code服务 </p>
 * <p>Copyright: Copyright (c) 2016</p>
 * <p>Company:    医百科技有限公司 </p>
 *
 * @author         <a href="yangwensheng@100doc.com.cn"/>杨文生</a>
 * @since      2020/9/17 16:22
 */
@Service
@Slf4j
public class SysGeneratorCodeServiceImpl implements SysGeneratorCodeService {

    @Resource
    private RedisService redisService;

    private final SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");



    @Override
    public String fetchDailyUUID(String key, Integer length, Boolean haveDay) {
        long num = 1L;
        key = RedisKeyPrefix.DAILYUUID + key;
        // 设置每天凌晨12点过期
        Long expireTime = getSecondsNextEarlyMorning();
        try {
            synchronized (this) {
                num = redisService.incr(key,1L,expireTime);
            }
        } catch (Exception ex) {
            log.error("Redis生成日序列号发生错误！", ex);
            throw new BusinessException("Redis生成日序列号发生错误");
        }
        return formatUUID(num,haveDay,length);
    }

    @Override
    public String fetchUUID(String key, Integer length, Boolean haveDay) {
        long num = 1L;
        key = RedisKeyPrefix.GLOBALUUID + key;
        try {
            synchronized (this) {
                num = redisService.incrNoExpire(key,1L);
            }
        } catch (Exception ex) {
            log.error("Redis生成全局序列号发生错误！", ex);
            throw new BusinessException("Redis生成全局序列号发生错误");
        }
        return formatUUID(num,haveDay,length);
    }

    @Override
    public String fetchDailyUUIDWithPrefix(String key, String prefix, Integer length, Boolean haveDay) {
        return prefix + fetchDailyUUID(key,length,haveDay);
    }

    @Override
    public String fetchUUIDWithPreFix(String key, String prefix, Integer length, Boolean haveDay) {
        return prefix + fetchUUID(key,length,haveDay);
    }

    private String formatUUID(Long num, Boolean haveDay, Integer length) {
        String id = String.valueOf(num);
        if (id.length() < length) {
            NumberFormat nf = NumberFormat.getInstance();
            nf.setGroupingUsed(false);
            nf.setMaximumIntegerDigits(length);
            nf.setMinimumIntegerDigits(length);
            id = nf.format(num);
        }
        Calendar now = new GregorianCalendar();
        String day = df.format(now.getTime());
        return haveDay ?  day + id : id;
    }



    /**
     * 获取年月日+当前小时数作为前缀
     * @return String
     */
    private String getIdPrefix() {
        Date date = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        //补两位,因为一年最多三位数
        String monthFormat = String.format("%1$02d", month+1);
        //补两位，因为日最多两位数
        String dayFormat = String.format("%1$02d", day);
        return year + monthFormat + dayFormat;
    }

    /**
     * 判断当前时间距离第二天凌晨的秒数
     *
     * @return 返回值单位为[s:秒]
     */
    public Long getSecondsNextEarlyMorning() {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_YEAR, 1);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return (cal.getTimeInMillis() - System.currentTimeMillis()) / 1000;
    }

}
